package pt.fct.mpc.lastfm.connectivity.bt;

import java.util.Set;

import pt.fct.mpc.lastfm.LastfmPreferences;
import pt.fct.mpc.lastfm.MainActivity;
import pt.fct.mpc.lastfm.R;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class LastfmBluetoothActivity
	extends Activity
{
	private static final String TAG = "Lastfm BT Activity";

	// This value will be passed to onActivityResult.
	private static final int REQUEST_ENABLE_BT = 1;

	private BluetoothAdapter bt_adapter;
	private Context context;
	
	private ArrayAdapter<String> paired_devices_adapter;
	private ArrayAdapter<String> new_devices_adapter;


	private final BroadcastReceiver intent_receiver = 
		new BroadcastReceiver()
		{
			@Override
			public void onReceive(Context context, Intent intent)
			{
				String action = intent.getAction();
				
				if (BluetoothDevice.ACTION_FOUND.equals(action))
				{
					// We just found a device.
					BluetoothDevice device = 
						intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
					
					// Only add to the list if this device is not bonded.
					if (device.getBondState() != BluetoothDevice.BOND_BONDED)
					{
						new_devices_adapter.add(device.getName() + "\n"
							+ device.getAddress());
					}
				} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
				{
					// Discovery has finished.
					setProgressBarIndeterminateVisibility(false);
					setTitle(R.string.lastfm_bt_select_device);
					
					if (new_devices_adapter.getCount() <= 0)
					{
						new_devices_adapter.add(
							getString(R.string.lastfm_bt_no_devices));
					}
				}
				
			}
		};


	// OnItemClickListener for all device's list views.
	private OnItemClickListener device_click_listener =
		new OnItemClickListener()
		{
			@Override
			public void onItemClick(AdapterView<?> parent, View view,
				int position, long id)
			{
				// If the user selected a remote device, then we should
				// stop inquiring since we won't need any more results.
				if (bt_adapter.isDiscovering())
					bt_adapter.cancelDiscovery();
				
				String info = ((TextView) view).getText().toString();
				// The MAC address is 17 characters long and they are the
				// last ones on the 'info' string. Simply, obtain them.
				String address = info.substring(info.length() - 17);
				
				Log.d(TAG, "Chosen device: "+info);
				
				String remote_uuid_str =
					getString(R.string.lastfm_bt_gateway_uuid);
				
				LastfmBluetoothGateway gateway;
				LastfmBluetoothManager bt_manager;
				try
				{
					gateway = new LastfmBluetoothGateway(address, remote_uuid_str);
					bt_manager = LastfmBluetoothManager.getInstance();
					bt_manager.startBluetooth(gateway);

				} catch (LastfmBluetoothException e)
				{
					e.printStackTrace();
					
					Toast.makeText(context, "Unable to connect to Gateway", 
						Toast.LENGTH_SHORT).show();
					
					MainActivity.setTemporaryPreference(
						LastfmPreferences.Temporary.PREF_BT_GW, false);
				}
				
				finish();
			}
		};
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		
		this.context = this;
		
		requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
		setContentView(R.layout.device_list);
		
		// Set default activity result.
		setResult(RESULT_CANCELED);
		
		// Set OnClickListener for 'Scan Devices' button.
		Button scan_button = (Button) findViewById(R.id.button_scan);
		scan_button.setOnClickListener(
			new OnClickListener()
			{
				@Override
				public void onClick(View v)
				{
					doDiscovery();
					v.setVisibility(View.GONE);
				}
			});

		// Set adapters responsible for keeping devices.
		paired_devices_adapter = 
			new ArrayAdapter<String>(context, R.layout.device_name);
		new_devices_adapter = 
			new ArrayAdapter<String>(context, R.layout.device_name);
		
		// Set up both views for presenting devices.
		ListView paired_devices_list_view = 
			(ListView) findViewById(R.id.paired_devices);
		paired_devices_list_view.setAdapter(paired_devices_adapter);
		paired_devices_list_view.setOnItemClickListener(device_click_listener);
		
		ListView new_devices_list_view = 
			(ListView) findViewById(R.id.new_devices);
		new_devices_list_view.setAdapter(new_devices_adapter);
		new_devices_list_view.setOnItemClickListener(device_click_listener);
		
		// Register receivers for broadcasts for when a device is found, and
		// for when the discovery has finished.
		IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
		this.registerReceiver(intent_receiver , filter);
		
		filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
		this.registerReceiver(intent_receiver, filter);
		
		// Set up bluetooth.		
		doSetupBluetooth();

		// Acquire paired devices and present them.
		Set<BluetoothDevice> paired_devices = bt_adapter.getBondedDevices();

		// If there are paired devices, add them to the list.
		if (paired_devices.size() > 0) {
			TextView paired_devices_title_view = 
				(TextView) findViewById(R.id.title_paired_devices);
			paired_devices_title_view.setVisibility(View.VISIBLE);
			
		    for (BluetoothDevice device : paired_devices) {
		        paired_devices_adapter.add(device.getName() + "\n" + device.getAddress());
		    }
		} else
		{
			paired_devices_adapter.add(getString(R.string.lastfm_bt_no_devices));
		}
	}
	
	@Override
	protected void onDestroy()
	{
		super.onDestroy();
		
		// Cancel any discovery currently happening.
		if (this.bt_adapter != null)
			this.bt_adapter.cancelDiscovery();
		
		this.unregisterReceiver(intent_receiver);
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		super.onActivityResult(requestCode, resultCode, data);
		
		if (requestCode == REQUEST_ENABLE_BT)
		{
			if (resultCode != Activity.RESULT_OK)
				showErrorDialogAndExit("Bluetooth must be enabled.");
		}
		
		setProgressBarIndeterminateVisibility(false);
	}

	protected void doDiscovery()
	{
		Log.d(TAG, "Doing Bluetooth Discovery");
		
		setProgressBarIndeterminateVisibility(true);
		setTitle(R.string.lastfm_bt_scanning);
		
		TextView title_new_devices_view = 
			(TextView) findViewById(R.id.title_new_devices);
		title_new_devices_view.setVisibility(View.VISIBLE);
		
		if (this.bt_adapter.isDiscovering())
			this.bt_adapter.cancelDiscovery();
		
		this.bt_adapter.startDiscovery();
		
	}

	/**
	 * Turn on bluetooth, if available and if the user allows such a thing.
	 */
	private void doSetupBluetooth()
	{
		this.bt_adapter = BluetoothAdapter.getDefaultAdapter();

		if (this.bt_adapter == null)
		{
			showErrorDialogAndExit("This device does not support Bluetooth.");
			finish();
		}

		if (this.bt_adapter.isEnabled() == false) 
		{
			setProgressBarIndeterminateVisibility(true);
			Intent enable_bt_intent = 
				new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(enable_bt_intent, REQUEST_ENABLE_BT);
			
		}
	}

	private void showErrorDialogAndExit(String message)
	{
		AlertDialog.Builder builder = new AlertDialog.Builder(context);
		
		builder.setMessage(message)
				.setCancelable(false)
				.setPositiveButton("OK", 
					new DialogInterface.OnClickListener()
					{
						@Override
						public void onClick(DialogInterface dialog, int which)
						{
							finish();
						}
					}
				);
		
		AlertDialog dialog = builder.create();
		dialog.show();
	}
}
